using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using star_questionnair.Models;
using star_questionnair.Models.Enum;
using star_questionnairquestionnair.Services;
using Microsoft.Extensions.Logging;

namespace star_questionnair.Services.impl;

public class DifferenceLevelQuestionAnalysisService : IDifferenceLevelQuestionAnalysisService
{
     private readonly IQuestionService _questionService;
    private readonly IHistoryService _historyService;
    private readonly IUserService _userService;
    private readonly IResponseService _responseService;
    private readonly ILogger<DifferenceLevelQuestionAnalysisService> _logger;

    public DifferenceLevelQuestionAnalysisService(
        IQuestionService questionService,
        IHistoryService historyService,
        IUserService userService,
        IResponseService responseService,
        ILogger<DifferenceLevelQuestionAnalysisService> logger)
    {
        _questionService = questionService;
        _historyService = historyService;
        _userService = userService;
        _responseService = responseService;
        _logger = logger;
    }


    // 获取某个维度（性别、年龄、公司、职位）上的平均得分
    private async Task<Dictionary<TKey, double>> GetDimensionAverageScoresAsync<TKey>(int questionId, Func<User, Task<TKey>> dimensionSelector)
    {
        var question = await _questionService.GetQuestionByIdAsync(questionId);

        if (!QuestionEnumExtensions.IsLevelType(question.Type)) return null;

        var answers = _historyService.GetAnswersByQuestionId(questionId);
        var totalScores = new Dictionary<TKey, int>();
        var countAnswers = new Dictionary<TKey, int>();

        foreach (var answer in answers)
        {
            var response = await _responseService.GetResponseByIdAsync(answer.ResponseId);
            var user = await _userService.GetByIdAsync(response.UserId);
            var dimension = await dimensionSelector(user);

            if (dimension == null) continue;

            totalScores[dimension] = totalScores.GetValueOrDefault(dimension, 0) + answer.Level;
            countAnswers[dimension] = countAnswers.GetValueOrDefault(dimension, 0) + 1;
        }

        var result = new Dictionary<TKey, double>();
        foreach (var dimension in totalScores.Keys)
        {
            var totalScore = totalScores[dimension];
            var count = countAnswers[dimension];
            result[dimension] = count == 0 ? 0.0 : (double)totalScore / count;
        }

        return result;
    }

    // 获取性别维度的平均得分
    public Task<Dictionary<bool, double>> GetGenderDifferenceAsync(int questionId)
    {
        return GetDimensionAverageScoresAsync<bool>(questionId, user => Task.FromResult(user.Gender));
    }

    // 获取年龄维度的平均得分
    public Task<Dictionary<string, double>> GetAgeDifferenceAsync(int questionId)
    {
        return GetDimensionAverageScoresAsync<string>(questionId, async user =>
        {
            var age = await _userService.CalculateUserAgeAsync(user.Id);
            return GetAgeStage(age);
        });
    }

    // 获取公司维度的平均得分
    public Task<Dictionary<string, double>> GetEnterpriseDifferenceAsync(int questionId)
    {
        return GetDimensionAverageScoresAsync<string>(questionId, user => Task.FromResult(user.Enterprise));
    }

    // 获取职位维度的平均得分
    public Task<Dictionary<string, double>> GetRoleDifferenceAsync(int questionId)
    {
        return GetDimensionAverageScoresAsync<string>(questionId, user => Task.FromResult(user.RoleName));
    }

    // 获取性别维度的各个等级比例
    public async Task<Dictionary<bool, Dictionary<int, double>>> GetGenderLevelProportionsAsync(int questionId)
    {
        var question = await _questionService.GetQuestionByIdAsync(questionId);

        if (!QuestionEnumExtensions.IsLevelType(question.Type)) return null;

        var result = await GetLevelProportionsByAttributeAsync(questionId, "gender");

        // 将 object 转换为 bool
        var genderResult = new Dictionary<bool, Dictionary<int, double>>();
        foreach (var entry in result)
        {
            if (entry.Key is bool gender)
            {
                genderResult[gender] = entry.Value;
            }
        }

        return genderResult;
    }

    // 获取年龄维度的各个等级比例
    public async Task<Dictionary<string, Dictionary<int, double>>> GetAgeLevelProportionsAsync(int questionId)
    {
        var question = await _questionService.GetQuestionByIdAsync(questionId);

        if (!QuestionEnumExtensions.IsLevelType(question.Type)) return null;
        var result = await GetLevelProportionsByAttributeAsync(questionId, "age");

        // 将 object 转换为 string（年龄阶段）
        var ageResult = new Dictionary<string, Dictionary<int, double>>();
        foreach (var entry in result)
        {
            if (entry.Key is string ageStage)
            {
                ageResult[ageStage] = entry.Value;
            }
        }

        return ageResult;
    }

    // 获取公司维度的各个等级比例
    public async Task<Dictionary<string, Dictionary<int, double>>> GetEnterpriseLevelProportionsAsync(int questionId)
    {
        var question = await _questionService.GetQuestionByIdAsync(questionId);

        if (!QuestionEnumExtensions.IsLevelType(question.Type)) return null;
        var result = await GetLevelProportionsByAttributeAsync(questionId, "enterprise");

        // 将 object 转换为 string
        var enterpriseResult = new Dictionary<string, Dictionary<int, double>>();
        foreach (var entry in result)
        {
            if (entry.Key is string enterprise)
            {
                enterpriseResult[enterprise] = entry.Value;
            }
        }

        return enterpriseResult;
    }

    // 获取职位维度的各个等级比例
    public async Task<Dictionary<string, Dictionary<int, double>>> GetRoleLevelProportionsAsync(int questionId)
    {
        var question = await _questionService.GetQuestionByIdAsync(questionId);

        if (!QuestionEnumExtensions.IsLevelType(question.Type)) return null;
        var result = await GetLevelProportionsByAttributeAsync(questionId, "role");

        // 将 object 转换为 string
        var roleResult = new Dictionary<string, Dictionary<int, double>>();
        foreach (var entry in result)
        {
            if (entry.Key is string role)
            {
                roleResult[role] = entry.Value;
            }
        }

        return roleResult;
    }

    // 计算各个维度（性别、年龄、公司、职位）上的等级占比
    private async Task<Dictionary<object, Dictionary<int, double>>> GetLevelProportionsByAttributeAsync(int questionId, string attribute)
    {
        var question = await _questionService.GetQuestionByIdAsync(questionId);

        if (!QuestionEnumExtensions.IsLevelType(question.Type)) return null;

        var answers = _historyService.GetAnswersByQuestionId(questionId);
        var levelCounts = new Dictionary<object, Dictionary<int, int>>();
        var totalAnswers = new Dictionary<object, int>();

        foreach (var answer in answers)
        {
            var response = await _responseService.GetResponseByIdAsync(answer.ResponseId);
            var user = await _userService.GetByIdAsync(response.UserId);

            object attributeValue = await GetAttributeValue(user, attribute);
            if (attributeValue == null) continue;

            if (!levelCounts.ContainsKey(attributeValue))
            {
                levelCounts[attributeValue] = new Dictionary<int, int>();
                totalAnswers[attributeValue] = 0;
            }

            int level = answer.Level;
            levelCounts[attributeValue][level] = levelCounts[attributeValue].GetValueOrDefault(level, 0) + 1;
            totalAnswers[attributeValue]++;
        }

        var result = new Dictionary<object, Dictionary<int, double>>();
        foreach (var attributeValue in levelCounts.Keys)
        {
            var levels = levelCounts[attributeValue];
            var totalCount = totalAnswers[attributeValue];
            var levelProportions = levels.ToDictionary(entry => entry.Key, entry => (double)entry.Value / totalCount);
            result[attributeValue] = levelProportions;
        }

        return result;
    }

    // 根据年龄计算对应的年龄段
    private string GetAgeStage(int age)
    {
        if (age >= 20 && age <= 25) return "20-25";
        if (age > 25 && age <= 30) return "25-30";
        if (age > 30 && age <= 35) return "30-35";
        if (age > 35 && age <= 40) return "35-40";
        if (age > 40 && age <= 45) return "40-45";
        if (age > 45 && age <= 50) return "45-50";
        if (age > 50) return "50+";

        return null;
    }

    // 获取指定属性的值（性别、公司、职位、年龄）
    private async Task<object> GetAttributeValue(User user, string attribute)
    {
        switch (attribute)
        {
            case "gender": return user.Gender;
            case "enterprise": return user.Enterprise;
            case "role": return user.RoleName;
            case "age":
                var age = await _userService.CalculateUserAgeAsync(user.Id);
                return GetAgeStage(age);
            default: return null;
        }
    }
}